%{
 open Ast;;
 let parse_error s = (* Called by the parser function on error *)
 print_endline  s;
 flush stdout
%}

%token <int> INT
%token PLUS MINUS MUL DIV
%token MATCH WITH PIPE ARROW NEW_LINE LPAREN RPAREN END
%token <string> IDENT
%token FUN IDENT FUN_ARROW LET IN EQ REC EOF

%left PLUS MINUS
%left MUL DIV
%left FUN IDENT FUN_ARROW
%left MATCH IN
%left LPAREN

%start main
%type <Ast.exp> main
%type <Ast.pattern> constant
%%

constant:
 IDENT                           { StringPat($1)}
| INT                      { IntPat($1)}
;
tinyexp:
 IDENT                           { StringConst($1)}
| INT                      { IntConst($1)}
| LPAREN funexp RPAREN            { $2 }
;

appexp:
tinyexp                            { $1}
| appexp tinyexp                   { App($1,$2)}
;

funexp : appexp                       { $1}
| funexp MUL funexp                  { Binop( Mul, $1, $3)}
| funexp DIV funexp                  { Binop( Div, $1, $3)}
| funexp PLUS funexp                 { Binop( Plus, $1, $3)}
| funexp MINUS funexp                { Binop( Minus,$1, $3)}
| FUN IDENT FUN_ARROW funexp         { Fun( $2,$4)}
| MATCH funexp WITH match_exp END    { Match($2,$4)}
| LET IDENT EQ funexp IN funexp      { Let ($2,$4,$6)}
| LET REC IDENT IDENT EQ funexp IN funexp { LetRec($3,$4,$6,$8)}
;


match_exp:
 match_case  match_exp  {$1::$2}
| match_case { [$1]}
;

match_case: PIPE constant ARROW funexp   { ($2,$4)}
;



main : funexp EOF              { $1}
%%
